home *** CD-ROM | disk | FTP | other *** search
/ Aminet 52 / Aminet 52 (2002)(GTI - Schatztruhe)[!][Dec 2002].iso / Aminet / util / moni / Scout-src.lha / source / objects / scout_patches.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-09-17  |  24.3 KB  |  679 lines

  1. /**
  2.  * Scout - The Amiga System Monitor
  3.  *
  4.  *------------------------------------------------------------------
  5.  *
  6.  * This program is free software; you can redistribute it and/or modify
  7.  * it under the terms of the GNU General Public License as published by
  8.  * the Free Software Foundation; either version 2 of the License, or
  9.  * any later version.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program; if not, write to the Free Software
  18.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  *
  20.  * You must not use this source code to gain profit of any kind!
  21.  *
  22.  *------------------------------------------------------------------
  23.  *
  24.  * @author Andreas Gelhausen
  25.  * @author Richard Körber <rkoerber@gmx.de>
  26.  */
  27.  
  28. #include "system_headers.h"
  29.  
  30. struct PatchesCallbackUserData {
  31.     APTR ud_List;
  32.     ULONG ud_Count;
  33. };
  34.  
  35. static __asm __saveds LONG patchlist_con2func(register __a2 Object *obj, register __a1 struct NList_ConstructMessage *msg, register __a0 struct Hook *hook)
  36. {
  37.     return AllocListEntry(msg->pool, msg->entry, sizeof(struct PatchEntry));
  38. }
  39.  
  40. MakeHook(patchlist_con2hook, patchlist_con2func);
  41.  
  42. static __asm __saveds LONG patchlist_des2func(register __a2 Object *obj, register __a1 struct NList_DestructMessage *msg, register __a0 struct Hook *hook)
  43. {
  44.     FreeListEntry(msg->pool, &msg->entry);
  45.  
  46.     return 0;
  47. }
  48.  
  49. MakeHook(patchlist_des2hook, patchlist_des2func);
  50.  
  51. static __asm __saveds LONG patchlist_dsp2func(register __a2 Object *obj, register __a1 struct NList_DisplayMessage *msg, register __a0 struct Hook *hook)
  52. {
  53.     struct PatchEntry *pe = (struct PatchEntry *)msg->entry;
  54.  
  55.     if (pe) {
  56.         msg->strings[0] = pe->pe_Address;
  57.         msg->strings[1] = pe->pe_Library;
  58.         msg->strings[2] = pe->pe_OffsetDec;
  59.         msg->strings[3] = pe->pe_OffsetHex;
  60.         msg->strings[4] = pe->pe_Function;
  61.         msg->strings[5] = pe->pe_State;
  62.         msg->strings[6] = pe->pe_Patcher;
  63.     } else {
  64.         msg->strings[0] = "Address";
  65.         msg->strings[1] = "Library";
  66.         msg->strings[2] = "Offset";
  67.         msg->strings[3] = "Hex";
  68.         msg->strings[4] = "Function";
  69.         msg->strings[5] = "State";
  70.         msg->strings[6] = "Patcher";
  71.         msg->preparses[0] = MUIX_B;
  72.         msg->preparses[1] = MUIX_B;
  73.         msg->preparses[2] = MUIX_B;
  74.         msg->preparses[3] = MUIX_B;
  75.         msg->preparses[4] = MUIX_B;
  76.         msg->preparses[5] = MUIX_B;
  77.         msg->preparses[6] = MUIX_B;
  78.     }
  79.  
  80.     return 0;
  81. }
  82.  
  83. MakeHook(patchlist_dsp2hook, patchlist_dsp2func);
  84.  
  85. static LONG patchlist_cmp2colfunc( struct PatchEntry *pe1,
  86.                                    struct PatchEntry *pe2,
  87.                                    ULONG column )
  88. {
  89.     LONG cmp = 0;
  90.  
  91.     switch (column) {
  92.         case 0: cmp = stricmp(pe1->pe_Address, pe2->pe_Address); break;
  93.         case 1: cmp = stricmp(pe1->pe_Library, pe2->pe_Library); break;
  94.         case 2: cmp = stricmp(pe1->pe_OffsetDec, pe2->pe_OffsetDec); break;
  95.         case 3: cmp = stricmp(pe1->pe_OffsetHex, pe2->pe_OffsetHex); break;
  96.         case 4: cmp = stricmp(pe1->pe_Function, pe2->pe_Function); if (cmp == 0) cmp = stricmp(pe1->pe_Patcher, pe2->pe_Patcher); break;
  97.         case 5: cmp = stricmp(pe1->pe_State, pe2->pe_State); break;
  98.         case 6: cmp = stricmp(pe1->pe_Patcher, pe2->pe_Patcher); break;
  99.     }
  100.  
  101.     return cmp;
  102. }
  103.  
  104. static __asm __saveds LONG patchlist_cmp2func(register __a2 Object *obj, register __a1 struct NList_CompareMessage *msg, register __a0 struct Hook *hook)
  105. {
  106.     LONG cmp;
  107.     struct PatchEntry *pe1, *pe2;
  108.     ULONG col1, col2;
  109.  
  110.     pe1 = (struct PatchEntry *)msg->entry1;
  111.     pe2 = (struct PatchEntry *)msg->entry2;
  112.     col1 = msg->sort_type & MUIV_NList_TitleMark_ColMask;
  113.     col2 = msg->sort_type2 & MUIV_NList_TitleMark2_ColMask;
  114.  
  115.     if (msg->sort_type == MUIV_NList_SortType_None) return 0;
  116.  
  117.     if (msg->sort_type & MUIV_NList_TitleMark_TypeMask) {
  118.         cmp = patchlist_cmp2colfunc(pe2, pe1, col1);
  119.     } else {
  120.         cmp = patchlist_cmp2colfunc(pe1, pe2, col1);
  121.     }
  122.  
  123.     if (cmp != 0 || col1 == col2) return cmp;
  124.  
  125.     if (msg->sort_type2 & MUIV_NList_TitleMark2_TypeMask) {
  126.         cmp = patchlist_cmp2colfunc(pe2, pe1, col2);
  127.     } else {
  128.         cmp = patchlist_cmp2colfunc(pe1, pe2, col2);
  129.     }
  130.  
  131.     return cmp;
  132. }
  133.  
  134. MakeHook(patchlist_cmp2hook, patchlist_cmp2func);
  135.  
  136. static void GetFunctionName( struct Library *lib,
  137.                              LONG offset,
  138.                              struct PatchEntry *pe )
  139. {
  140.     ULONG absOffset = abs(offset);
  141.  
  142.     if ((absOffset <= LIB_VECTSIZE * 6 && lib->lib_Node.ln_Type == NT_DEVICE) ||
  143.         (absOffset <= LIB_VECTSIZE * 4 && lib->lib_Node.ln_Type == NT_LIBRARY)) {
  144.         UBYTE *help;
  145.  
  146.         switch (absOffset) {
  147.             case LIB_VECTSIZE * 1: help = "Open";    break;
  148.             case LIB_VECTSIZE * 2: help = "Close";   break;
  149.             case LIB_VECTSIZE * 3: help = "Expunge"; break;
  150.             case LIB_VECTSIZE * 4: help = "ExtFunc"; break;
  151.             case LIB_VECTSIZE * 5: help = "BeginIO"; break;
  152.             case LIB_VECTSIZE * 6: help = "AbortIO"; break;
  153.             default:               help = ""; break;
  154.         }
  155.         stccpy(pe->pe_Function, help, sizeof(pe->pe_Function));
  156.     } else {
  157.         if (lib->lib_Node.ln_Name) {
  158.             if (IdentifyBase) {
  159.                 switch (IdFunctionTags(lib->lib_Node.ln_Name, offset, IDTAG_FuncNameStr, pe->pe_Function,
  160.                                                                       IDTAG_StrLength, sizeof(pe->pe_Function),
  161.                                                                       TAG_DONE)) {
  162.                     case IDERR_NOFD:
  163.                         stccpy(pe->pe_Function, txtNoFDFile, sizeof(pe->pe_Function));
  164.                         break;
  165.  
  166.                     case IDERR_NOMEM:
  167.                         pe->pe_Function[0] = 0x00;
  168.                         break;
  169.  
  170.                     case IDERR_OFFSET:
  171.                         stccpy(pe->pe_Function, txtNoFunctionEntry, sizeof(pe->pe_Function));
  172.                         break;
  173.                 }
  174.             } else {
  175.                 stccpy(pe->pe_Function, msgNoIdentifyLibrary, sizeof(pe->pe_Function));
  176.             }
  177.         } else {
  178.             stccpy(pe->pe_Function, txtNoFDFile, sizeof(pe->pe_Function));
  179.         }
  180.     }
  181. }
  182.  
  183. static void IterateSaferPatchesList( struct MinList *tmplist,
  184.                                      struct PatchPort *pp )
  185. {
  186.     struct LibPatchList *ll;
  187.  
  188.     NoReqOn();
  189.  
  190.     ITERATE_LIST(&pp->pp_PatchList, struct LibPatchList *, ll) {
  191.         struct LibPatchNode *ln;
  192.  
  193.         ITERATE_LIST(&ll->ll_PatchList, struct LibPatchNode *, ln) {
  194.             struct LibPatchEntry *le;
  195.  
  196.             ITERATE_LIST(&ln->ln_PatchList, struct LibPatchEntry *, le) {
  197.                 struct PatchEntry *pe;
  198.  
  199.                 if (pe = AllocVec(sizeof(struct PatchEntry), MEMF_PUBLIC)) {
  200.                     ULONG absOffset;
  201.  
  202.                     absOffset = abs(ln->ln_Offset);
  203.  
  204.                     pe->pe_Addr = le;
  205.                     _snprintf(pe->pe_Address, sizeof(pe->pe_Address), "$%08lx", le->le_NewEntry);
  206.                     pe->pe_LibraryAddr = ll->ll_LibBase;
  207.                     stccpy(pe->pe_Library, nonetest(ll->ll_LibBase->lib_Node.ln_Name), sizeof(pe->pe_Library));
  208.                     pe->pe_Offset = ln->ln_Offset;
  209.                     _snprintf(pe->pe_OffsetDec, sizeof(pe->pe_OffsetDec), "-%ld", absOffset);
  210.                     _snprintf(pe->pe_OffsetHex, sizeof(pe->pe_OffsetHex), "-$%04lx", absOffset);
  211.  
  212.                     GetFunctionName(ll->ll_LibBase, ln->ln_Offset, pe);
  213.  
  214.                     if (le->le_Flags & LEF_DISABLED) {
  215.                         stccpy(pe->pe_State, txtPatchDisabled, sizeof(pe->pe_State));
  216.                     } else if (le->le_Flags & LEF_REMOVED) {
  217.                         stccpy(pe->pe_State, txtPatchRemoved, sizeof(pe->pe_State));
  218.                     } else {
  219.                         stccpy(pe->pe_State, txtPatchActive, sizeof(pe->pe_State));
  220.                     }
  221.  
  222.                     stccpy(pe->pe_Type, "SAFERPATCHES", sizeof(pe->pe_Type));
  223.  
  224.                     stccpy(pe->pe_Patcher, nonetest(le->le_Patcher), sizeof(pe->pe_Patcher));
  225.  
  226.                     AddTail((struct List *)tmplist, (struct Node *)pe);
  227.                 }
  228.             }
  229.         }
  230.     }
  231.  
  232.     NoReqOff();
  233. }
  234.  
  235. static void IteratePatchControlList( struct MinList *tmplist,
  236.                                      struct Library *PatchBase )
  237. {
  238.     struct PatchControlNode *list;
  239.  
  240.     if (list = GetPatchList()) {
  241.         struct PatchControlNode *pcn = list;
  242.  
  243.         NoReqOn();
  244.  
  245.         while (pcn) {
  246.             struct PatchEntry *pe;
  247.  
  248.             if (pe = AllocVec(sizeof(struct PatchEntry), MEMF_PUBLIC)) {
  249.                 ULONG absOffset;
  250.  
  251.                 absOffset = abs(pcn->pcn_Offset);
  252.  
  253.                 pe->pe_Addr = pcn;
  254.                 _snprintf(pe->pe_Address, sizeof(pe->pe_Address), "$%08lx", pcn->pcn_FunctionAddress);
  255.                 pe->pe_LibraryAddr = pcn->pcn_Library;
  256.                 stccpy(pe->pe_Library, nonetest(pcn->pcn_Library->lib_Node.ln_Name), sizeof(pe->pe_Library));
  257.                 pe->pe_Offset = pcn->pcn_Offset;
  258.                 _snprintf(pe->pe_OffsetDec, sizeof(pe->pe_OffsetDec), "-%ld", absOffset);
  259.                 _snprintf(pe->pe_OffsetHex, sizeof(pe->pe_OffsetHex), "-$%04lx", absOffset);
  260.  
  261.                 GetFunctionName(pcn->pcn_Library, pcn->pcn_Offset, pe);
  262.  
  263.                 stccpy(pe->pe_State, txtPatchActive, sizeof(pe->pe_State));
  264.                 stccpy(pe->pe_Patcher, nonetest(pcn->pcn_TaskName), sizeof(pe->pe_Patcher));
  265.                 stccpy(pe->pe_Type, "PATCHCONTROL", sizeof(pe->pe_Type));
  266.  
  267.                 AddTail((struct List *)tmplist, (struct Node *)pe);
  268.             }
  269.  
  270.             pcn = pcn->pcn_Next;
  271.         }
  272.  
  273.         NoReqOff();
  274.     }
  275.  
  276.     FreePatchList(list);
  277. }
  278.  
  279. static void IterateSetManList( struct MinList *tmplist,
  280.                                struct SetManPort *sp )
  281. {
  282.     if (stricmp(sp->sp_Version, SETMAN_VERSION) == 0) {
  283.         struct SetManNode *sn;
  284.  
  285.         ObtainSemaphore(&sp->sp_Semaphore);
  286.  
  287.         NoReqOn();
  288.  
  289.         ITERATE_LIST(&sp->sp_PatchList, struct SetManNode *, sn) {
  290.             struct PatchEntry *pe;
  291.  
  292.             if (pe = AllocVec(sizeof(struct PatchEntry), MEMF_PUBLIC)) {
  293.                 ULONG absOffset;
  294.  
  295.                 absOffset = abs(sn->sn_Offset);
  296.  
  297.                 pe->pe_Addr = sn;
  298.                 _snprintf(pe->pe_Address, sizeof(pe->pe_Address), "$%08lx", sn->sn_SetFunc);
  299.                 pe->pe_LibraryAddr = sn->sn_Library;
  300.                 stccpy(pe->pe_Library, nonetest(sn->sn_Library->lib_Node.ln_Name), sizeof(pe->pe_Library));
  301.                 pe->pe_Offset = sn->sn_Offset;
  302.                 _snprintf(pe->pe_OffsetDec, sizeof(pe->pe_OffsetDec), "-%ld", absOffset);
  303.                 _snprintf(pe->pe_OffsetHex, sizeof(pe->pe_OffsetHex), "-$%04lx", absOffset);
  304.  
  305.                 GetFunctionName(sn->sn_Library, sn->sn_Offset, pe);
  306.  
  307.                 if (sn->sn_SetFunc == NULL) {
  308.                     stccpy(pe->pe_State, txtPatchRemoved, sizeof(pe->pe_State));
  309.                 } else if (sn->sn_Jmp1 == JMPCODE) {
  310.                     stccpy(pe->pe_State, txtPatchActive, sizeof(pe->pe_State));
  311.                 } else {
  312.                     stccpy(pe->pe_State, txtPatchDisabled, sizeof(pe->pe_State));
  313.                 }
  314.  
  315.                 stccpy(pe->pe_Patcher, nonetest(sn->sn_TaskName), sizeof(pe->pe_Patcher));
  316.  
  317.                 stccpy(pe->pe_Type, "SETMAN", sizeof(pe->pe_Type));
  318.  
  319.                 AddTail((struct List *)tmplist, (struct Node *)pe);
  320.             }
  321.         }
  322.  
  323.         NoReqOff();
  324.  
  325.         ReleaseSemaphore(&sp->sp_Semaphore);
  326.     } else {
  327.         UBYTE wantversion[4];
  328.  
  329.         stccpy(wantversion, SETMAN_VERSION, sizeof(wantversion));
  330.  
  331.         MyRequest(msgErrorContinue, msgWrongSetManVersion, *((ULONG *)wantversion), *((ULONG *)sp->sp_Version));
  332.     }
  333. }
  334.  
  335. static void ReceiveList( void (* callback)( struct PatchEntry *pe, void *userData ),
  336.                          void *userData )
  337. {
  338.     struct PatchEntry *pe;
  339.  
  340.     if (pe = tbAllocVecPooled(globalPool, sizeof(struct PatchEntry))) {
  341.         if (SendDaemon("GetPatchList")) {
  342.             while (ReceiveDecodedEntry((UBYTE *)pe, sizeof(struct PatchEntry))) {
  343.                 callback(pe, userData);
  344.             }
  345.         }
  346.  
  347.         tbFreeVecPooled(globalPool, pe);
  348.     }
  349. }
  350.  
  351. static void IterateList( void (* callback)( struct PatchEntry *pe, void *userData ),
  352.                          void *userData )
  353. {
  354.     struct MinList tmplist;
  355.     struct PatchEntry *pe, *_pe;
  356.     struct PatchPort *pp;
  357.     struct SetManPort *sp;
  358.     struct Library *pc;
  359.  
  360.     NewList((struct List *)&tmplist);
  361.  
  362.     Forbid();
  363.     pp = (struct PatchPort *)FindPort(PATCHPORT_NAME);
  364.     sp = (struct SetManPort *)FindPort(SETMANPORT_NAME);
  365.     pc = (struct Library *)OpenResource(PATCHRES_NAME);
  366.     Permit();
  367.  
  368.     if (pp) {
  369.         IterateSaferPatchesList(&tmplist, pp);
  370.     } else if (pc) {
  371.         IteratePatchControlList(&tmplist, pc);
  372.     } else if (sp) {
  373.         IterateSetManList(&tmplist, sp);
  374.     } else {
  375.         MyRequest(msgErrorContinue, msgControlProgramNotInstalled);
  376.     }
  377.  
  378.     ITERATE_CHANGING_LIST(&tmplist, struct PatchEntry *, pe, _pe) {
  379.         callback(pe, userData);
  380.         FreeVec(pe);
  381.     }
  382. }
  383.  
  384. static void UpdateCallback( struct PatchEntry *pe,
  385.                             void *userData )
  386. {
  387.     struct PatchesCallbackUserData *ud = (struct PatchesCallbackUserData *)userData;
  388.  
  389.     InsertSortedEntry(ud->ud_List, pe);
  390.     ud->ud_Count++;
  391. }
  392.  
  393. static void PrintCallback( struct PatchEntry *pe,
  394.                            void *userData )
  395. {
  396.     PrintFOneLine((BPTR)userData, " %s %-25.25s %s %-25.25s %-8s %s\n", pe->pe_Address, pe->pe_Library, pe->pe_OffsetHex, pe->pe_Function, pe->pe_State, pe->pe_Patcher);
  397. }
  398.  
  399. static void SendCallback( struct PatchEntry *pe,
  400.                           void *userData )
  401. {
  402.     SendEncodedEntry((UBYTE *)pe, sizeof(struct PatchEntry));
  403. }
  404.  
  405. static ULONG __saveds mNew( struct IClass *cl,
  406.                             Object *obj,
  407.                             struct opSet *msg )
  408. {
  409.     APTR patchlist, patchtext, patchcount, updateButton, printButton, enableButton, disableButton, exitButton;
  410.  
  411.     if (obj = (Object *)DoSuperNew(cl, obj,
  412.         MUIA_HelpNode, PatchesText,
  413.         MUIA_Window_ID, MakeID('P','T','C','H'),
  414.         WindowContents, VGroup,
  415.  
  416.             Child, patchlist = MyNListviewObject(MakeID('P','T','L','V'), "BAR,BAR,BAR P=" MUIX_R ",BAR P=" MUIX_R ",BAR,BAR P=" MUIX_C ",BAR", &patchlist_con2hook, &patchlist_des2hook, &patchlist_dsp2hook, &patchlist_cmp2hook, TRUE),
  417.             Child, MyBelowListview(&patchtext, &patchcount),
  418.  
  419.             Child, MyVSpace(4),
  420.  
  421.             Child, HGroup, MUIA_Group_SameSize, TRUE,
  422.                 Child, updateButton   = MakeButton(txtUpdate),
  423.                 Child, printButton    = MakeButton(txtPrint),
  424.                 Child, enableButton   = MakeButton(txtEnable),
  425.                 Child, disableButton  = MakeButton(txtDisable),
  426.                 Child, exitButton     = MakeButton(txtExit),
  427.             End,
  428.         End,
  429.         TAG_MORE, msg->ops_AttrList))
  430.     {
  431.         struct PatchesWinData *pwd = INST_DATA(cl, obj);
  432.         APTR parent;
  433.  
  434.         pwd->pwd_PatchList = patchlist;
  435.         pwd->pwd_PatchText = patchtext;
  436.         pwd->pwd_PatchCount = patchcount;
  437.         pwd->pwd_EnableButton = enableButton;
  438.         pwd->pwd_DisableButton = disableButton;
  439.  
  440.         parent = (APTR)GetTagData(MUIA_Window_ParentWindow, (ULONG)NULL, msg->ops_AttrList);
  441.  
  442.         set(obj, MUIA_Window_Title, MyGetWindowTitle("PATCHES", pwd->pwd_Title, sizeof(pwd->pwd_Title)));
  443.         set(obj, MUIA_Window_ActiveObject, patchlist);
  444.         set(patchlist, MUIA_NList_MultiSelect, MUIV_NList_MultiSelect_Default);
  445.         set(enableButton, MUIA_Disabled, TRUE);
  446.         set(disableButton, MUIA_Disabled, TRUE);
  447.  
  448.         DoMethod(parent,        MUIM_Window_AddChildWindow, obj);
  449.         DoMethod(obj,           MUIM_Notify, MUIA_Window_CloseRequest, TRUE,           MUIV_Notify_Application, 5, MUIM_Application_PushMethod, parent, 2, MUIM_Window_RemChildWindow, obj);
  450.         DoMethod(patchlist,     MUIM_Notify, MUIA_NList_Active,        MUIV_EveryTime, obj,                     1, MUIM_PatchesWin_ListChange);
  451.         DoMethod(updateButton,  MUIM_Notify, MUIA_Pressed,             FALSE,          obj,                     1, MUIM_PatchesWin_Update);
  452.         DoMethod(printButton,   MUIM_Notify, MUIA_Pressed,             FALSE,          obj,                     1, MUIM_PatchesWin_Print);
  453.         DoMethod(enableButton,  MUIM_Notify, MUIA_Pressed,             FALSE,          obj,                     1, MUIM_PatchesWin_Enable);
  454.         DoMethod(disableButton, MUIM_Notify, MUIA_Pressed,             FALSE,          obj,                     1, MUIM_PatchesWin_Disable);
  455.         DoMethod(exitButton,    MUIM_Notify, MUIA_Pressed,             FALSE,          obj,                     3, MUIM_Set, MUIA_Window_CloseRequest, TRUE);
  456.         DoMethod(patchlist,     MUIM_NList_Sort3, MUIV_NList_Sort3_SortType_1, MUIV_NList_SortTypeAdd_None, MUIV_NList_Sort3_SortType_Both);
  457.  
  458.         Forbid();
  459.         pwd->pwd_SetManPort = (struct SetManPort *)FindPort(SETMANPORT_NAME);
  460.         Permit();
  461.     }
  462.  
  463.     return (ULONG)obj;
  464. }
  465.  
  466. static ULONG __saveds mDispose( struct IClass *cl,
  467.                                 Object *obj,
  468.                                 struct opSet *msg )
  469. {
  470.     struct PatchesWinData *pwd = INST_DATA(cl, obj);
  471.  
  472.     set(obj, MUIA_Window_Open, FALSE);
  473.     DoMethod(pwd->pwd_PatchList, MUIM_NList_Clear);
  474.  
  475.     return (DoSuperMethodA(cl, obj, msg));
  476. }
  477.  
  478. static ULONG __saveds mUpdate( struct IClass *cl,
  479.                                Object *obj,
  480.                                Msg msg )
  481. {
  482.     struct PatchesWinData *pwd = INST_DATA(cl, obj);
  483.     struct PatchesCallbackUserData ud;
  484.  
  485.     ApplicationSleep(TRUE);
  486.     set(pwd->pwd_PatchList, MUIA_NList_Quiet, TRUE);
  487.     DoMethod(pwd->pwd_PatchList, MUIM_NList_Clear);
  488.  
  489.     ud.ud_List = pwd->pwd_PatchList;
  490.     ud.ud_Count = 0;
  491.  
  492.     if (clientstate) {
  493.         ReceiveList(UpdateCallback, &ud);
  494.     } else {
  495.         IterateList(UpdateCallback, &ud);
  496.     }
  497.  
  498.     SetCountText(pwd->pwd_PatchCount, ud.ud_Count);
  499.     MySetContents(pwd->pwd_PatchText, "");
  500.  
  501.     set(pwd->pwd_PatchList, MUIA_NList_Quiet, FALSE);
  502.     set(pwd->pwd_PatchList, MUIA_NList_Active, MUIV_NList_Active_Off);
  503.     set(pwd->pwd_EnableButton, MUIA_Disabled, TRUE);
  504.     set(pwd->pwd_DisableButton, MUIA_Disabled, TRUE);
  505.     ApplicationSleep(FALSE);
  506.  
  507.     return 0;
  508. }
  509.  
  510. static ULONG __saveds mPrint( struct IClass *cl,
  511.                               Object *obj,
  512.                               Msg msg )
  513. {
  514.     PrintPatches(NULL);
  515.  
  516.     return 0;
  517. }
  518.  
  519. static ULONG __saveds mListChange( struct IClass *cl,
  520.                                    Object *obj,
  521.                                    Msg msg )
  522. {
  523.     struct PatchesWinData *pwd = INST_DATA(cl, obj);
  524.     struct PatchEntry *pe;
  525.  
  526.     if (pe = (struct PatchEntry *)GetActiveEntry(pwd->pwd_PatchList)) {
  527.         MySetContents(pwd->pwd_PatchText, "%s %s/%s()", pe->pe_Address, pe->pe_Library, pe->pe_Function);
  528.         if (!clientstate && stricmp(pe->pe_Type, "SAFERPATCHES") == 0) {
  529.             set(pwd->pwd_EnableButton, MUIA_Disabled, FALSE);
  530.             set(pwd->pwd_DisableButton, MUIA_Disabled, FALSE);
  531.         }
  532.     }
  533.  
  534.     return 0;
  535. }
  536.  
  537. static ULONG __saveds mEnable( struct IClass *cl,
  538.                                Object *obj,
  539.                                Msg msg )
  540. {
  541.     struct PatchesWinData *pwd = INST_DATA(cl, obj);
  542.     ULONG id = MUIV_NList_NextSelected_Start;
  543.  
  544.     while (TRUE) {
  545.         struct PatchEntry *pe;
  546.  
  547.         DoMethod(pwd->pwd_PatchList, MUIM_NList_NextSelected, &id);
  548.         if (id == MUIV_NList_NextSelected_End) break;
  549.  
  550.         DoMethod(pwd->pwd_PatchList, MUIM_NList_GetEntry, id, &pe);
  551.         if (pe) {
  552.             struct LibPatchEntry *le = (struct LibPatchEntry *)pe->pe_Addr;
  553.  
  554.             if (stricmp(pe->pe_Type, "SAFERPATCHES") == 0) {
  555.                 if ((le->le_Flags & LEF_DISABLED) && !(le->le_Flags & LEF_REMOVED)) {
  556.                     SetFunction(pe->pe_LibraryAddr, pe->pe_Offset, (APTR)le->le_NewEntry);
  557.                     le->le_Flags &= ~LEF_DISABLED;
  558.                     stccpy(pe->pe_State, txtPatchActive, sizeof(pe->pe_State));
  559.                     RedrawActiveEntry(pwd->pwd_PatchList);
  560.                 }
  561.             } else if (stricmp(pe->pe_Type, "SETMAN") == 0) {
  562.                 struct SetManNode *sn = (struct SetManNode *)pe->pe_Addr;
  563.  
  564.                 ObtainSemaphore(&pwd->pwd_SetManPort->sp_Semaphore);
  565.  
  566.                 if (sn->sn_Jmp1 == BRACODE && sn->sn_SetFunc != NULL) {
  567.                     sn->sn_Jmp1 = JMPCODE;
  568.                     CacheClearU();
  569.  
  570.                     stccpy(pe->pe_State, txtPatchActive, sizeof(pe->pe_State));
  571.                     RedrawActiveEntry(pwd->pwd_PatchList);
  572.                 }
  573.  
  574.                 ReleaseSemaphore(&pwd->pwd_SetManPort->sp_Semaphore);
  575.             }
  576.  
  577.             DoMethod(pwd->pwd_PatchList, MUIM_NList_Select, id, MUIV_NList_Select_Off, NULL);
  578.             id = MUIV_NList_NextSelected_Start;
  579.         }
  580.     }
  581.  
  582.     return 0;
  583. }
  584.  
  585. static ULONG __saveds mDisable( struct IClass *cl,
  586.                                 Object *obj,
  587.                                 Msg msg )
  588. {
  589.     struct PatchesWinData *pwd = INST_DATA(cl, obj);
  590.     ULONG id = MUIV_NList_NextSelected_Start;
  591.     ULONG disableMode = 1;
  592.  
  593.     while (TRUE) {
  594.         struct PatchEntry *pe;
  595.  
  596.         DoMethod(pwd->pwd_PatchList, MUIM_NList_NextSelected, &id);
  597.         if (id == MUIV_NList_NextSelected_End) break;
  598.         if (disableMode == 0) break;
  599.  
  600.         DoMethod(pwd->pwd_PatchList, MUIM_NList_GetEntry, id, &pe);
  601.         if (pe) {
  602.             struct LibPatchEntry *le = (struct LibPatchEntry *)pe->pe_Addr;
  603.  
  604.             if (stricmp(pe->pe_Type, "SAFERPATCHES") == 0) {
  605.                 if (!(le->le_Flags & LEF_DISABLED) && !(le->le_Flags & LEF_REMOVED)) {
  606.                     if (disableMode != 2) disableMode = MyRequest(msgYesAllNoAbort, msgWantToDisablePatches);
  607.  
  608.                     if (disableMode == 1 || disableMode == 2) {
  609.                         SetFunction(pe->pe_LibraryAddr, pe->pe_Offset, (APTR)&le->le_Jmp);
  610.                         le->le_Flags |= LEF_DISABLED;
  611.                         stccpy(pe->pe_State, txtPatchDisabled, sizeof(pe->pe_State));
  612.                         RedrawActiveEntry(pwd->pwd_PatchList);
  613.                     }
  614.                 }
  615.             } else if (stricmp(pe->pe_Type, "SETMAN") == 0) {
  616.                 struct SetManNode *sn = (struct SetManNode *)pe->pe_Addr;
  617.  
  618.                 ObtainSemaphore(&pwd->pwd_SetManPort->sp_Semaphore);
  619.  
  620.                 if (sn->sn_Jmp1 == JMPCODE && sn->sn_SetFunc != NULL) {
  621.                     if (disableMode != 2) disableMode = MyRequest(msgYesAllNoAbort, msgWantToDisablePatches);
  622.  
  623.                     if (disableMode == 1 || disableMode == 2) {
  624.  
  625.                         sn->sn_Jmp1 = BRACODE;
  626.                         CacheClearU();
  627.  
  628.  
  629.                         stccpy(pe->pe_State, txtPatchActive, sizeof(pe->pe_State));
  630.                         RedrawActiveEntry(pwd->pwd_PatchList);
  631.                     }
  632.                 }
  633.  
  634.                 ReleaseSemaphore(&pwd->pwd_SetManPort->sp_Semaphore);
  635.             }
  636.  
  637.             DoMethod(pwd->pwd_PatchList, MUIM_NList_Select, id, MUIV_NList_Select_Off, NULL);
  638.             id = MUIV_NList_NextSelected_Start;
  639.         }
  640.     }
  641.  
  642.     return 0;
  643. }
  644.  
  645. ULONG __asm __saveds PatchesWinDispatcher( register __a0 struct IClass *cl,
  646.                                            register __a2 Object *obj,
  647.                                            register __a1 Msg msg )
  648. {
  649.     switch (msg->MethodID) {
  650.         case OM_NEW:                     return (mNew(cl, obj, (APTR)msg));
  651.         case OM_DISPOSE:                 return (mDispose(cl, obj, (APTR)msg));
  652.         case MUIM_PatchesWin_Update:     return (mUpdate(cl, obj, (APTR)msg));
  653.         case MUIM_PatchesWin_Print:      return (mPrint(cl, obj, (APTR)msg));
  654.         case MUIM_PatchesWin_Enable:     return (mEnable(cl, obj, (APTR)msg));
  655.         case MUIM_PatchesWin_Disable:    return (mDisable(cl, obj, (APTR)msg));
  656.         case MUIM_PatchesWin_ListChange: return (mListChange(cl, obj, (APTR)msg));
  657.     }
  658.  
  659.     return (DoSuperMethodA(cl, obj, msg));
  660. }
  661.  
  662. void PrintPatches( char *filename )
  663. {
  664.     BPTR handle;
  665.  
  666.     if (handle = HandlePrintStart(filename)) {
  667.         PrintFOneLine(handle, "\n  Address  Library                   Offset Function                  Flags    Patcher\n\n");
  668.         IterateList(PrintCallback, (void *)handle);
  669.     }
  670.  
  671.     HandlePrintStop();
  672. }
  673.  
  674. void SendPatchList( void )
  675. {
  676.     IterateList(SendCallback, NULL);
  677. }
  678.  
  679.